package yunjiao.javatutorials.guava.concurrent;

import com.google.common.util.concurrent.AbstractIdleService;
import com.google.common.util.concurrent.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 *  配置管理服务示例
 *
 * @author yangyunjiao
 */
public class ConfigurationService extends AbstractIdleService {
    private final Map<String, String> configCache = new ConcurrentHashMap<>();
    private ScheduledExecutorService configReloadExecutor;

    @Override
    protected void startUp() throws Exception {
        System.out.println("Initializing Configuration Service");

        // 加载初始配置
        loadConfiguration();

        // 创建定时重新加载配置的执行器
        configReloadExecutor = Executors.newSingleThreadScheduledExecutor(r -> {
            Thread t = new Thread(r, "config-reloader");
            t.setDaemon(true);
            return t;
        });

        // 每30秒重新加载配置
        configReloadExecutor.scheduleAtFixedRate(
                this::reloadConfiguration,
                3, 3, TimeUnit.SECONDS
        );

        System.out.println("Configuration Service started with " + configCache.size() + " entries");
    }

    @Override
    protected void shutDown() throws Exception {
        System.out.println("Shutting down Configuration Service");

        if (configReloadExecutor != null) {
            configReloadExecutor.shutdown();
            try {
                if (!configReloadExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
                    configReloadExecutor.shutdownNow();
                }
            } catch (InterruptedException e) {
                configReloadExecutor.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }

        configCache.clear();
        System.out.println("Configuration Service stopped");
    }

    private void loadConfiguration() {
        // 模拟从外部源加载配置
        configCache.put("database.url", "jdbc:h2:mem:testdb");
        configCache.put("database.username", "sa");
        configCache.put("cache.timeout", "300");
        configCache.put("log.level", "INFO");
    }

    private void reloadConfiguration() {
        try {
            System.out.println("Reloading configuration...");
            // 在实际应用中，这里会从配置中心或文件重新加载
            loadConfiguration();
        } catch (Exception e) {
            System.err.println("Failed to reload configuration: " + e.getMessage());
        }
    }

    public String getConfig(String key) {
        if (!isRunning()) {
            throw new IllegalStateException("Service is not running");
        }
        return configCache.get(key);
    }

    public String getConfig(String key, String defaultValue) {
        return configCache.getOrDefault(key, defaultValue);
    }

    // 添加监听器示例
    public void addListener() {
        addListener(new Service.Listener() {
            @Override
            public void running() {
                System.out.println("Configuration Service is now RUNNING");
            }

            @Override
            public void stopping(Service.State from) {
                System.out.println("Configuration Service is stopping from state: " + from);
            }

            @Override
            public void terminated(Service.State from) {
                System.out.println("Configuration Service terminated from state: " + from);
            }

            @Override
            public void failed(Service.State from, Throwable failure) {
                System.err.println("Configuration Service failed from state: " + from);
                failure.printStackTrace();
            }
        }, Executors.newSingleThreadExecutor());
    }

    public static void main(String[] args) throws Exception {
        ConfigurationService configService = new ConfigurationService();
        configService.addListener();

        // 启动服务
        configService.startAsync().awaitRunning();

        // 使用服务
        System.out.println("Database URL: " + configService.getConfig("database.url"));
        System.out.println("Log Level: " + configService.getConfig("log.level"));

        // 运行一段时间
        Thread.sleep(10000);

        // 停止服务
        configService.stopAsync().awaitTerminated();
    }
}
